package uk.ac.nott.cs.g53dia.bee;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

import sun.security.action.GetBooleanAction;
import uk.ac.nott.cs.g53dia.Action;
import uk.ac.nott.cs.g53dia.Bee;
import uk.ac.nott.cs.g53dia.Cell;
import uk.ac.nott.cs.g53dia.CommunicateAction;
import uk.ac.nott.cs.g53dia.DepositNectarAction;
import uk.ac.nott.cs.g53dia.EmptyCell;
import uk.ac.nott.cs.g53dia.Flower;
import uk.ac.nott.cs.g53dia.HarvestAction;
import uk.ac.nott.cs.g53dia.LayEggAction;
import uk.ac.nott.cs.g53dia.MoveAction;
import uk.ac.nott.cs.g53dia.MoveTowardsAction;
import uk.ac.nott.cs.g53dia.Nest;
import uk.ac.nott.cs.g53dia.Point;
import uk.ac.nott.cs.g53dia.RestAction;
import utils.ComparatorFactory;
import utils.Constants;
import utils.General;
import utils.RandomGenerator;

public class BeeActionPlanner {

  private static final float COMMUNICATION_SAMPLES_PROB = 0.05f;
  private static final float DELIBERATION_FROM_RESTING_PROB = 0.035f;
  private static final float DELIBERATION_FROM_HARVESTING_PROB = 0.055f;
  private static final int DEFAULT_RANGE_FOR_SEARCH = 10;
  private Map<Point, Cell> cells;
  private List<Set<Point>> flowersOfType;
  private int numBees;
  private BeeYieldApproximator approximator;
  private int previousEnergyDelta;
  private boolean change = false;
  private boolean significantChange = false;

  public BeeActionPlanner(Map<Point, Cell> cells, List<Set<Point>> flowersOfType, int numBees,
      BeeYieldApproximator approximator) {
    this.cells = cells;
    this.flowersOfType = flowersOfType;
    this.numBees = numBees;
    this.approximator = approximator;
  }

  private int shouldCommunicate(int numBeesOnMyCell, int[] hvntComm, Bee bee, int day, boolean onFlower) {
    int sum = 0;
    if (numBeesOnMyCell != 1) {
      List<Bee> visibleBees = bee.getBeesOnMyCell();
      visibleBees.remove(bee);
      for (Bee vBee : visibleBees) {
        int ratio = day < 2 ? (2 - day) : 1;
        sum += hvntComm[vBee.getId()] * ratio;
        if (onFlower)
          hvntComm[vBee.getId()]--; // no need to communicate, when both are
        // sampling the same flower
        if (!onFlower && change && day == 0) {
          change = false;
          sum += 100 * ratio;
        }
      }
    }
    return sum;
  }

  private int shouldGoForCommunication(int[] hvntComm, Bee bee, int day) {
    int sum = 0;
    List<Bee> visibleBees = bee.getVisibleBees();
    visibleBees.remove(bee);
    for (Bee vBee : visibleBees) {
      if (vBee.getPosition().equals(bee.getPosition()))
        continue;
      int ratio = day < 2 ? (2 - day) : 1;
      sum += hvntComm[vBee.getId()] * ratio;
      if (change && day == 0) {
        change = false;
        sum += 100 * ratio;
      }
    }

    return sum;
  }

  public Queue<Action> planNewSequence(Bee bee, final int energy, long timestep, Point nest, int numBeesOnMyCell,
      int energyDelta, int[] hvntComm, int day) {
    Point actLoc = bee.getPosition();
    Queue<Action> plan = new LinkedList<Action>() {

      {
        add(new RestAction());
      }
    };

    // return to nest if full
    if (energy == Bee.MAX_ENERGY) {
      if (Constants.DEBUG) {
        System.out.println("200 energy reached");
      }
      previousEnergyDelta = -1;
      return moveBeeTo(bee, nest);
    }

    // communication
    int shouldCommunicate = shouldCommunicate(numBeesOnMyCell, hvntComm, bee, day,
        (cells.get(actLoc) instanceof Flower));
    if (energy > CommunicateAction.MAX_SAMPLES_PRICE && shouldCommunicate > 400) {
      previousEnergyDelta = -1;
      return new LinkedList<Action>() {

        {
          add(new CommunicateAction(CommunicateAction.DANCE_FLOWER_SAMPLES));
        }
      };
    }

    // scenarios for different cells
    if (cells.get(actLoc) instanceof Nest) {
      if (energy > 20) {
        previousEnergyDelta = -1;
        plan = new LinkedList<Action>() {

          {
            add(new DepositNectarAction(energy - 8));
          }
        };
      } else {
        List<Float> weights = approximator.guessYields(timestep);
        if (General.sumFloats(weights.toArray(new Float[0])) < Flower.NUM_TYPES + 0.2f
            && ((Nest) cells.get(actLoc)).foodSupply() >= Nest.EGG_COST) { // night
          // probably
          plan = new LinkedList<Action>() {

            {
              add(new LayEggAction());
            }
          };
          // lay an egg
        } else {
          plan = goForNectar(bee, timestep, day, hvntComm, weights);
        }
      }
    } else if (cells.get(actLoc) instanceof Flower) {
      if (((Flower) cells.get(actLoc)).getNumFlowers() >= numBeesOnMyCell) {
        plan = harvestUntilFull(bee, energy, timestep, energyDelta, day, hvntComm);
      } else {
        previousEnergyDelta = -1;
        plan = goForNectarRandom(bee);
      }
    } else if (cells.get(actLoc) instanceof EmptyCell) {
      previousEnergyDelta = -1;
      plan = goForNectar(bee, timestep, day, hvntComm);
    }
    return plan;
  }

  // private int utility(Queue<Action> plan) {
  //    
  // }

  private Queue<Action> moveBeeTo(Bee bee, Point end) {
    Point start = bee.getPosition();
    Queue<Action> plan = new LinkedList<Action>();
    if (end.equals(start)) {
      if (Constants.DEBUG) {
        System.err.println("start and end location are equal");
      }
      // plan.add(new MoveAction(RandomGenerator.getRandomInt(8)));
      plan.add(new RestAction());
      return plan;
    }
    int d = General.distance(start, end);
    plan.addAll(duplicateN(new MoveTowardsAction(end), d));
    return plan;
  }

  private Queue<Action> goForNectar(Bee bee, long timestep, int day, int[] hvntComm) {
    return goForNectar(bee, timestep, day, hvntComm, approximator.guessYields(timestep + 3));
  }

  private Queue<Action> goForNectarOfFlowertype(Bee bee, long timestep, int day, int[] hvntComm, List<Float> weights,
      int flowerType) {
    if (Constants.DEBUG) {
      System.out.println("Fl. weights (" + Flower.FLOWER_COLORS[0] + ", " + Flower.FLOWER_COLORS[1] + ", "
          + Flower.FLOWER_COLORS[2] + ", " + Flower.FLOWER_COLORS[3] + ", " + Flower.FLOWER_COLORS[4] + ", " + "): "
          + weights);
    }
    if (General.sumFloats(weights.toArray(new Float[0])) < Flower.NUM_TYPES) {
      if (howCleverAmI(timestep) > 0.025f && shouldGoForCommunication(hvntComm, bee, day) > 650) {
        if (RandomGenerator.getRandomFloat() < COMMUNICATION_SAMPLES_PROB) {
          return moveBeeTo(bee, findABeeForCommunication(bee, hvntComm));
        }
      }
      return new LinkedList<Action>() {

        {
          add(new RestAction());
        }
      };
    }
    List<Point> flowers = findClosestFlowers(bee.getPosition(), flowerType);
    List<Float> valuations = new ArrayList<Float>(flowers.size());
    for (Point p : flowers) {
      int dis = General.distance(p, bee.getPosition());
      int numOfFlowers = ((Flower) cells.get(p)).getNumFlowers();
      int numOfBees = 0;
      List<Bee> visibleBees = bee.getVisibleBees();
      visibleBees.remove(bee);
      for (Bee visBee : visibleBees) {
        if (visBee.getPosition().equals(p)) {
          numOfBees++;
        }
      }
      valuations.add(((float) numOfFlowers - numOfBees) / ((dis == 0) ? 0.75f : (dis * dis)));
    }
    if (Constants.DEBUG) {
      System.out.println("Possible flowers of type " + Flower.FLOWER_COLORS[flowerType] + " are: " + flowers);
      System.out.println(".. they have these valuations " + valuations);
    }
    int ind = General.powerRoulette(valuations);
    return moveBeeTo(bee, flowers.get(ind));
  }

  private Queue<Action> goForNectar(Bee bee, long timestep, int day, int[] hvntComm, List<Float> weights) {
    // int type = General.rouletteWheel(weights);
    // int type = General.winnerTakesAll(weights);
    int type = General.powerRoulette(weights);
    return goForNectarOfFlowertype(bee, timestep, day, hvntComm, weights, type);
  }

  private Queue<Action> goForNectarRandom(Bee bee) {
    int type = RandomGenerator.getRandomInt(Flower.NUM_TYPES);
    List<Point> flowers = findClosestFlowers(bee.getPosition(), type);
    int ind = RandomGenerator.getRandomInt(flowers.size());
    return moveBeeTo(bee, flowers.get(ind));
  }

  private Queue<Action> harvestUntilFull(Bee bee, final int energy, long timestep, int energyDelta, int day,
      int[] hvntComm) {
    Queue<Action> plan = new LinkedList<Action>();
    int change = 0;
    if (previousEnergyDelta != -1) {
      change = energyDelta - previousEnergyDelta;
    }
    if (change > 0) {
      this.change = true;
    }
    if (energyDelta == 0) {
      // System.out.println("clever: " + howCleverAmI(timestep));
      if (howCleverAmI(timestep) > 0.025f && shouldGoForCommunication(hvntComm, bee, day) > 600) {
        if (RandomGenerator.getRandomFloat() < COMMUNICATION_SAMPLES_PROB) {
          return moveBeeTo(bee, findABeeForCommunication(bee, hvntComm));
        }
        if (RandomGenerator.getRandomFloat() < DELIBERATION_FROM_RESTING_PROB) {
          return goForNectar(bee, timestep, day, hvntComm);
        }
      }
      if (Bee.MAX_ENERGY - energy > BeeYieldApproximator.PRECISION * 2) {
        plan.addAll(duplicateN(new RestAction(), BeeYieldApproximator.PRECISION * 2));
        plan.add(new HarvestAction());
      } else {
        plan.addAll(duplicateN(new RestAction(), Bee.MAX_ENERGY - energy));
      }
    } else {
      int index = approximator.getBetterFlower(timestep, energyDelta);
      if (index != -1 && (RandomGenerator.getRandomFloat() < DELIBERATION_FROM_HARVESTING_PROB)) {
        plan = goForNectarOfFlowertype(bee, timestep, day, hvntComm, approximator.guessYields(timestep + 3), index);
      } else {
        plan.add(new HarvestAction());
      }
    }
    this.previousEnergyDelta = energyDelta;
    return plan;
  }

  private Point findABeeForCommunication(Bee bee, int[] hvntComm) {
    int max = 0;
    int i = -1;
    int index = 0;
    List<Bee> visibleBees = bee.getVisibleBees();
    visibleBees.remove(bee);
    if (visibleBees.size() == 0) {
      return null;
    }
    for (Bee vBee : visibleBees) {
      i++;
      if (vBee.getPosition().equals(bee.getPosition()))
        continue;
      if (hvntComm[vBee.getId()] > max) {
        max = hvntComm[vBee.getId()];
        index = i;
      }
    }
    return visibleBees.get(index).getPosition();
  }

  private float howCleverAmI(long timestep) {
    return approximator.howClever(timestep);
  }

  public List<Point> findClosestFlowers(Point actPos, int type) {
    List<Point> result = findClosestFlowers(actPos, type, DEFAULT_RANGE_FOR_SEARCH);
    if (result.size() == 0) {
      if (Constants.DEBUG) {
        System.out.println("small range");
      }
      return findClosestFlowers(actPos, type, DEFAULT_RANGE_FOR_SEARCH + 5);
    } else
      return result;
  }

  public List<Point> findClosestFlowers(Point actPos, int type, int range) {
    Set<Point> flowers = flowersOfType.get(type);
    List<Point> surrounding = generateSurroundingOfSize(actPos, range);
    List<Point> result = new ArrayList<Point>(numBees);
    int i = 0;
    for (Point p : surrounding) {
      if (flowers.contains(p)) {
        result.add(p);
        if (i++ == numBees) {
          break; // enough
        }
      }
    }
    return result;
  }

  private List<Point> generateSurroundingOfSize(Point actPos, int n) {
    List<Point> result = new ArrayList<Point>((2 * n + 1) * (2 * n + 1));
    for (int i = actPos.x - n; i <= actPos.x + n; i++) {
      for (int j = actPos.y - n; j <= actPos.y + n; j++) {
        result.add(new Point(i, j));
      }
    }
    Collections.sort(result, ComparatorFactory.getClosePointComparatorRelativeTo(actPos));
    return result;
  }

  private static List<Action> duplicateN(Action a, int n) {
    List<Action> result = new LinkedList<Action>();
    for (int i = 0; i < n; i++) {
      result.add(a);
    }
    return result;
  }

  public static class StaticExplorationPlans {

    public static final int DOUBLE_VIEW = 2 * Bee.VIEW_RANGE;
    // public static final Queue<Action> scoutLoop1Old = new
    // LinkedList<Action>(){
    // {
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 4*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 4*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 2*DOUBLE_VIEW +
    // Bee.VIEW_RANGE));
    // }
    // };
    //
    // public static final Queue<Action> scoutLoop2Old = new
    // LinkedList<Action>(){
    // {
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 4*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 4*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 2*DOUBLE_VIEW +
    // Bee.VIEW_RANGE));
    // }
    // };
    //
    // public static final Queue<Action> scoutLoop3Old = new
    // LinkedList<Action>(){
    // {
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 5*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 2*DOUBLE_VIEW +
    // Bee.VIEW_RANGE));
    // }
    // };
    //
    // public static final Queue<Action> scoutLoop4Old = new
    // LinkedList<Action>(){
    // {
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 5*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 2*DOUBLE_VIEW +
    // Bee.VIEW_RANGE));
    // }
    // };
    //
    // public static final Queue<Action> scout4Loop1 = new LinkedList<Action>(){
    // {
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 4*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 3*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.EAST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), DOUBLE_VIEW-1));
    // }
    // };
    // public static final Queue<Action> scout4Loop2 = new LinkedList<Action>(){
    // {
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 4*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 3*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.WEST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), DOUBLE_VIEW-1));
    // }
    // };
    // public static final Queue<Action> scout4Loop3 = new LinkedList<Action>(){
    // {
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 4*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 3*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTH), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), DOUBLE_VIEW-1));
    // }
    // };
    // public static final Queue<Action> scout4Loop4 = new LinkedList<Action>(){
    // {
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 4*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 3*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTH), 2*DOUBLE_VIEW));
    // addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), DOUBLE_VIEW-1));
    // }
    // };
    //

    public static final Queue<Action> scout8Loop1 = new LinkedList<Action>() {

      {
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 8 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 9 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.EAST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 3 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTH), 7 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), DOUBLE_VIEW));
        addAll(duplicateN(new RestAction(), CommunicateAction.MAX_POSITIONS_PRICE));
        add(new CommunicateAction(CommunicateAction.DANCE_FLOWER_POSITIONS));
      }
    };
    public static final Queue<Action> scout8Loop2 = new LinkedList<Action>() {

      {
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 8 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 9 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.WEST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 3 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTH), 7 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), DOUBLE_VIEW));
        addAll(duplicateN(new RestAction(), CommunicateAction.MAX_POSITIONS_PRICE));
        add(new CommunicateAction(CommunicateAction.DANCE_FLOWER_POSITIONS));
      }
    };
    public static final Queue<Action> scout8Loop3 = new LinkedList<Action>() {

      {
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 8 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 9 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTH), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 3 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.WEST), 7 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), DOUBLE_VIEW));
        addAll(duplicateN(new RestAction(), CommunicateAction.MAX_POSITIONS_PRICE));
        add(new CommunicateAction(CommunicateAction.DANCE_FLOWER_POSITIONS));
      }
    };
    public static final Queue<Action> scout8Loop4 = new LinkedList<Action>() {

      {
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 8 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 9 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTH), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 3 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.EAST), 7 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), DOUBLE_VIEW));
        addAll(duplicateN(new RestAction(), CommunicateAction.MAX_POSITIONS_PRICE));
        add(new CommunicateAction(CommunicateAction.DANCE_FLOWER_POSITIONS));
      }
    };
    public static final Queue<Action> scout8Loop5 = new LinkedList<Action>() {

      {
        addAll(duplicateN(new MoveAction(MoveAction.WEST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 6 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 10 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 5 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTH), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.WEST), 9 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new RestAction(), CommunicateAction.MAX_POSITIONS_PRICE));
        add(new CommunicateAction(CommunicateAction.DANCE_FLOWER_POSITIONS));
      }
    };
    public static final Queue<Action> scout8Loop6 = new LinkedList<Action>() {

      {
        addAll(duplicateN(new MoveAction(MoveAction.EAST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 6 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 10 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 5 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTH), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.EAST), 9 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new RestAction(), CommunicateAction.MAX_POSITIONS_PRICE));
        add(new CommunicateAction(CommunicateAction.DANCE_FLOWER_POSITIONS));
      }
    };
    public static final Queue<Action> scout8Loop7 = new LinkedList<Action>() {

      {
        addAll(duplicateN(new MoveAction(MoveAction.NORTH), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 6 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 10 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 5 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.WEST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTH), 9 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new RestAction(), CommunicateAction.MAX_POSITIONS_PRICE));
        add(new CommunicateAction(CommunicateAction.DANCE_FLOWER_POSITIONS));
      }
    };
    public static final Queue<Action> scout8Loop8 = new LinkedList<Action>() {

      {
        addAll(duplicateN(new MoveAction(MoveAction.SOUTH), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 6 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), 10 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHWEST), 5 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHWEST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.NORTHEAST), 4 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.EAST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTH), 9 * DOUBLE_VIEW));
        addAll(duplicateN(new MoveAction(MoveAction.SOUTHEAST), 2 * DOUBLE_VIEW));
        addAll(duplicateN(new RestAction(), CommunicateAction.MAX_POSITIONS_PRICE));
        add(new CommunicateAction(CommunicateAction.DANCE_FLOWER_POSITIONS));
      }
    };

  }
}
